﻿/*!
 * \file WTSDataDef.hpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WonderTrader行情数据定义文件
 * \details 本文件定义了所有行情数据相关的核心类型和数据结构，包括：
 *          - WTSValueArray: 数值数组容器，提供高效的数值存储和操作
 *          - WTSKlineSlice/WTSKlineData: K线数据容器，支持多周期K线数据管理
 *          - WTSTickData: 逐笔行情数据，包含完整的市场快照信息
 *          - WTSOrdQueData: 委托队列数据，Level2市场深度信息
 *          - WTSOrdDtlData: 委托明细数据，订单簿详细信息
 *          - WTSTransData: 成交明细数据，实时成交记录
 *          - WTSHisTickData: 历史Tick数据容器
 *          - 各种Slice类: 高效的数据切片访问器
 *          
 *          所有数据类型均继承自WTSObject，支持引用计数管理，
 *          提供高性能的内存管理和数据访问机制。
 */
#pragma once
#include <stdlib.h>
#include <vector>
#include <deque>
#include <string.h>
#include <chrono>

#include "WTSObject.hpp"

#include "WTSTypes.h"
#include "WTSMarcos.h"
#include "WTSStruct.h"
#include "WTSCollection.hpp"

using namespace std;

#pragma warning(disable:4267)


NS_WTP_BEGIN
class WTSContractInfo;
/*!
 * \brief 数值数组容器类
 * \details 高性能的动态数值数组，基于std::vector实现，专门用于存储和操作double类型的数值序列。
 *          提供了丰富的数组操作接口，包括索引访问、范围查询、统计计算等功能。
 *          支持负索引访问（从末尾倒数），以及数据的动态添加和修改。
 *          
 *          主要特性：
 *          - 高效的数值存储和访问
 *          - 支持正负索引的灵活访问模式
 *          - 提供范围内最大值/最小值查询
 *          - 动态数组大小调整
 *          - 内存安全的边界检查
 *          
 *          适用场景：
 *          - 技术指标计算的数据源
 *          - 价格序列存储
 *          - 量化分析的数值缓存
 */
class WTSValueArray : public WTSObject
{
protected:
	vector<double>	m_vecData;

public:
	/*!
	 * \brief 创建数值数组对象
	 * \details 工厂方法，创建一个新的WTSValueArray实例并返回指针。
	 *          创建的对象已初始化为空数组状态，可以立即使用。
	 * \return WTSValueArray* 新创建的数值数组对象指针
	 * \note 调用者负责管理返回对象的生命周期，需要调用release()释放内存
	 */
	static WTSValueArray* create()
	{
		WTSValueArray* pRet = new WTSValueArray;
		pRet->m_vecData.clear();
		return pRet;
	}

	/*!
	 * \brief 获取数组长度
	 * \return uint32_t 数组中元素的数量
	 */
	inline uint32_t	size() const{ return m_vecData.size(); }
	
	/*!
	 * \brief 检查数组是否为空
	 * \return bool true表示数组为空，false表示包含元素
	 */
	inline bool		empty() const{ return m_vecData.empty(); }

	/*!
	 * \brief 获取指定位置的数值
	 * \details 安全的数组元素访问接口，支持负索引（从末尾倒数）。
	 *          当索引超出有效范围时，返回INVALID_DOUBLE而不抛出异常。
	 * \param idx 数组索引，支持负值（-1表示最后一个元素）
	 * \return double 指定位置的数值，超出范围时返回INVALID_DOUBLE
	 */
	inline double		at(uint32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= m_vecData.size())
			return INVALID_DOUBLE;

		return m_vecData[idx];
	}

	/*!
	 * \brief 索引转换函数
	 * \details 将负索引转换为正索引，支持从数组末尾倒数访问。
	 *          负索引-1表示最后一个元素，-2表示倒数第二个元素，以此类推。
	 * \param idx 原始索引值，可以是正数或负数
	 * \return int32_t 转换后的正索引值
	 */
	inline int32_t		translateIdx(int32_t idx) const
	{
		if(idx < 0)
		{
			return m_vecData.size()+idx;
		}

		return idx;
	}

	/*!
	 * \brief 查找指定范围内的最大值
	 * \details 在给定的索引范围内查找最大值，支持负索引和绝对值比较。
	 *          忽略INVALID_DOUBLE值，只计算有效数值的最大值。
	 * \param head 起始索引（支持负值）
	 * \param tail 结束索引（支持负值）
	 * \param isAbs 是否比较绝对值，默认为false
	 * \return double 范围内的最大值，无有效值时返回INVALID_DOUBLE
	 */
	double		maxvalue(int32_t head, int32_t tail, bool isAbs = false) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		uint32_t begin = min(head, tail);
		uint32_t end = max(head, tail);

		if(begin <0 || begin >= m_vecData.size() || end < 0 || end > m_vecData.size())
			return INVALID_DOUBLE;

		double maxValue = INVALID_DOUBLE;
		for(uint32_t i = begin; i <= end; i++)
		{
			if(m_vecData[i] == INVALID_DOUBLE)
				continue;

			if(maxValue == INVALID_DOUBLE)
				maxValue = isAbs?abs(m_vecData[i]):m_vecData[i];
			else
				maxValue = max(maxValue, isAbs?abs(m_vecData[i]):m_vecData[i]);
		}

		//if (maxValue == INVALID_DOUBLE)
		//	maxValue = 0.0;

		return maxValue;
	}

	/*!
	 * \brief 查找指定范围内的最小值
	 * \details 在给定的索引范围内查找最小值，支持负索引和绝对值比较。
	 *          忽略INVALID_DOUBLE值，只计算有效数值的最小值。
	 * \param head 起始索引（支持负值）
	 * \param tail 结束索引（支持负值）
	 * \param isAbs 是否比较绝对值，默认为false
	 * \return double 范围内的最小值，无有效值时返回INVALID_DOUBLE
	 */
	double		minvalue(int32_t head, int32_t tail, bool isAbs = false) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		uint32_t begin = min(head, tail);
		uint32_t end = max(head, tail);

		if(begin <0 || begin >= m_vecData.size() || end < 0 || end > m_vecData.size())
			return INVALID_DOUBLE;

		double minValue = INVALID_DOUBLE;
		for(uint32_t i = begin; i <= end; i++)
		{
			if (m_vecData[i] == INVALID_DOUBLE)
				continue;

			if(minValue == INVALID_DOUBLE)
				minValue = isAbs?abs(m_vecData[i]):m_vecData[i];
			else
				minValue = min(minValue, isAbs?abs(m_vecData[i]):m_vecData[i]);
		}

		//if (minValue == INVALID_DOUBLE)
		//	minValue = 0.0;

		return minValue;
	}

	/*!
	 * \brief 在数组末尾追加数值
	 * \details 使用emplace_back高效地在数组末尾添加新元素，自动扩展数组容量。
	 * \param val 要添加的数值
	 */
	inline void		append(double val)
	{
		m_vecData.emplace_back(val);
	}

	/*!
	 * \brief 设置指定位置的数值
	 * \details 修改指定索引位置的元素值，包含边界检查，超出范围时忽略操作。
	 * \param idx 数组索引位置
	 * \param val 要设置的新数值
	 */
	inline void		set(uint32_t idx, double val)
	{
		if(idx < 0 || idx >= m_vecData.size())
			return;

		m_vecData[idx] = val;
	}

	/*!
	 * \brief 重新调整数组大小
	 * \details 改变数组的元素数量，新增元素使用指定的默认值填充。
	 *          如果新大小小于当前大小，则截断数组；如果更大，则扩展数组。
	 * \param uSize 新的数组大小
	 * \param val 新元素的默认值，默认为INVALID_DOUBLE
	 */
	inline void		resize(uint32_t uSize, double val = INVALID_DOUBLE)
	{
		m_vecData.resize(uSize, val);
	}

	/*!
	 * \brief 数组索引运算符重载（可修改版本）
	 * \details 提供类似std::vector的下标访问语法，返回可修改的元素引用。
	 *          注意：不进行边界检查，调用者需确保索引有效。
	 * \param idx 数组索引
	 * \return double& 指定位置元素的引用
	 */
	inline double&		operator[](uint32_t idx)
	{
		return m_vecData[idx];
	}

	/*!
	 * \brief 数组索引运算符重载（只读版本）
	 * \details 提供类似std::vector的下标访问语法，返回元素的常量副本。
	 *          注意：不进行边界检查，调用者需确保索引有效。
	 * \param idx 数组索引
	 * \return double 指定位置的元素值
	 */
	inline double		operator[](uint32_t idx) const
	{
		return m_vecData[idx];
	}

	/*!
	 * \brief 获取底层数据容器的引用
	 * \details 返回内部std::vector<double>的直接引用，用于高效的批量数据操作。
	 *          调用者可以直接操作底层容器，但需注意保持数据一致性。
	 * \return std::vector<double>& 底层数据容器的引用
	 * \warning 直接操作底层容器可能破坏对象状态，请谨慎使用
	 */
	inline std::vector<double>& getDataRef()
	{
		return m_vecData;
	}
};

/*!
 * \brief K线数据切片容器
 * \details 高性能的K线数据切片管理器，专门用于处理分块存储的K线数据。
 *          支持将当日实时数据与历史数据进行无缝拼接，提供统一的访问接口。
 *          
 *          核心特性：
 *          - 分块数据管理：支持多个内存块的K线数据存储
 *          - 统一索引访问：将多个数据块抽象为连续的数组访问
 *          - 高效内存利用：避免大量数据的重复拷贝
 *          - 实时数据拼接：支持历史数据与实时数据的动态组合
 *          
 *          应用场景：
 *          - 策略回测中的历史数据加载
 *          - 实盘交易中的实时数据追加
 *          - 大量K线数据的内存优化管理
 *          - 多周期K线数据的统一访问
 */
class WTSKlineSlice : public WTSObject
{
private:
	char			_code[MAX_INSTRUMENT_LENGTH];
	WTSKlinePeriod	_period;
	uint32_t		_times;
	typedef std::pair<WTSBarStruct*, uint32_t> BarBlock;
	std::vector<BarBlock> _blocks;
	uint32_t		_count;

protected:
	WTSKlineSlice()
		: _period(KP_Minute1)
		, _times(1)
		, _count(0)
	{

	}

	inline int32_t		translateIdx(int32_t idx) const
	{
		int32_t totalCnt = _count;
		if (idx < 0)
		{
			return max(0, totalCnt + idx);
		}

		return idx;
	}


public:
	/*!
	 * \brief 创建K线数据切片对象
	 * \details 工厂方法，创建一个新的WTSKlineSlice实例。可选择性地添加初始数据块。
	 * \param code 合约代码
	 * \param period K线周期类型
	 * \param times K线周期倍数
	 * \param bars 初始K线数据指针，可为NULL
	 * \param count 初始数据条数，bars为NULL时应为0
	 * \return WTSKlineSlice* 新创建的K线切片对象指针
	 */
	static WTSKlineSlice* create(const char* code, WTSKlinePeriod period, uint32_t times, WTSBarStruct* bars = NULL, int32_t count = 0)
	{
		WTSKlineSlice *pRet = new WTSKlineSlice;
		wt_strcpy(pRet->_code, code);
		pRet->_period = period;
		pRet->_times = times;
		if(bars)
			pRet->_blocks.emplace_back(BarBlock(bars, count));
		pRet->_count = count;

		return pRet;
	}

	/*!
	 * \brief 追加数据块
	 * \details 在切片末尾添加新的K线数据块，用于动态扩展数据。
	 * \param bars K线数据指针，不能为NULL
	 * \param count 数据条数，必须大于0
	 * \return bool 成功返回true，参数无效返回false
	 */
	inline bool appendBlock(WTSBarStruct* bars, uint32_t count)
	{
		if (bars == NULL || count == 0)
			return false;

		_count += count;
		_blocks.emplace_back(BarBlock(bars, count));
		return true;
	}

	/*!
	 * \brief 获取数据块数量
	 * \return std::size_t 当前管理的数据块总数
	 */
	inline std::size_t	get_block_counts() const
	{
		return _blocks.size();
	}

	/*!
	 * \brief 获取指定数据块的地址
	 * \param blkIdx 数据块索引
	 * \return WTSBarStruct* 数据块起始地址，索引无效时返回NULL
	 */
	inline WTSBarStruct*	get_block_addr(std::size_t blkIdx)
	{
		if (blkIdx >= _blocks.size())
			return NULL;

		return _blocks[blkIdx].first;
	}

	/*!
	 * \brief 获取指定数据块的大小
	 * \param blkIdx 数据块索引
	 * \return uint32_t 数据块中的K线条数，索引无效时返回0
	 */
	inline uint32_t get_block_size(std::size_t blkIdx)
	{
		if (blkIdx >= _blocks.size())
			return 0;

		return _blocks[blkIdx].second;
	}

	/*!
	 * \brief 获取指定位置的K线数据（可修改版本）
	 * \details 通过统一索引访问分块存储的K线数据，支持负索引从末尾倒数。
	 *          内部自动定位到对应的数据块并返回具体位置的指针。
	 * \param idx 数据索引，支持负值（-1表示最后一条K线）
	 * \return WTSBarStruct* K线数据指针，索引无效时返回NULL
	 */
	inline WTSBarStruct*	at(int32_t idx)
	{
		if (_count == 0)
			return NULL;

		idx = translateIdx(idx);
		do
		{
			for (auto& item : _blocks)
			{
				if ((uint32_t)idx >= item.second)
					idx -= item.second;
				else
					return item.first + idx;
			}
		} while (false);

		return NULL;
	}

	/*!
	 * \brief 获取指定位置的K线数据（只读版本）
	 * \details 通过统一索引访问分块存储的K线数据，支持负索引从末尾倒数。
	 *          内部自动定位到对应的数据块并返回具体位置的常量指针。
	 * \param idx 数据索引，支持负值（-1表示最后一条K线）
	 * \return const WTSBarStruct* K线数据常量指针，索引无效时返回NULL
	 */
	inline const WTSBarStruct*	at(int32_t idx) const
	{
		if (_count == 0)
			return NULL;

		idx = translateIdx(idx);
		do
		{
			for (auto& item : _blocks)
			{
				if ((uint32_t)idx >= item.second)
					idx -= item.second;
				else
					return item.first + idx;
			}
		} while (false);
		return NULL;
	}


	/*!
	 * \brief 查找指定范围内的最高价
	 * \details 在给定的索引范围内查找最高价格，支持负索引和跨数据块查询。
	 * \param head 起始索引（支持负值）
	 * \param tail 结束索引（支持负值）
	 * \return double 范围内的最高价，数据为空时可能返回不确定值
	 */
	double		maxprice(int32_t head, int32_t tail) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		int32_t begin = max(0,min(head, tail));
		int32_t end = min(max(head, tail), size() - 1);

		double maxValue = this->at(begin)->high;
		for (int32_t i = begin; i <= end; i++)
		{
			maxValue = max(maxValue, at(i)->high);
		}
		return maxValue;
	}

	/*!
	 * \brief 查找指定范围内的最低价
	 * \details 在给定的索引范围内查找最低价格，支持负索引和跨数据块查询。
	 * \param head 起始索引（支持负值）
	 * \param tail 结束索引（支持负值）
	 * \return double 范围内的最低价，数据为空时可能返回不确定值
	 */
	double		minprice(int32_t head, int32_t tail) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		int32_t begin = max(0, min(head, tail));
		int32_t end = min(max(head, tail), size() - 1);

		double minValue = at(begin)->low;
		for (int32_t i = begin; i <= end; i++)
		{
			minValue = min(minValue, at(i)->low);
		}

		return minValue;
	}

	/*!
	 * \brief 获取K线数据总条数
	 * \return int32_t 所有数据块中的K线总数
	 */
	inline int32_t	size() const{ return _count; }
	
	/*!
	 * \brief 检查切片是否为空
	 * \return bool true表示无K线数据，false表示包含数据
	 */
	inline bool	empty() const{ return _count == 0; }

	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串指针
	 */
	inline const char*	code() const{ return _code; }
	
	/*!
	 * \brief 设置合约代码
	 * \param code 合约代码字符串
	 */
	inline void		setCode(const char* code){ wt_strcpy(_code, code); }


	/*!
	 * \brief 提取K线字段数据
	 * \details 从指定范围的K线数据中提取特定字段，生成数值数组。
	 *          支持跨数据块的字段提取，常用于技术指标计算。
	 * \param type 字段类型，支持KFT_OPEN、KFT_HIGH、KFT_LOW、KFT_CLOSE、KFT_VOLUME、KFT_SVOLUME、KFT_DATE
	 * \param head 起始索引，默认为0
	 * \param tail 结束索引，默认为-1（表示最后一条）
	 * \return WTSValueArray* 包含提取数据的数值数组，无数据时返回NULL
	 */
	WTSValueArray*	extractData(WTSKlineFieldType type, int32_t head = 0, int32_t tail = -1) const
	{
		if (_count == 0)
			return NULL;

		head = translateIdx(head);
		tail = translateIdx(tail);

		int32_t begin = max(0, min(head, tail));
		int32_t end = min(max(head, tail), size() - 1);

		WTSValueArray *vArray = NULL;

		vArray = WTSValueArray::create();

		for (int32_t i = begin; i <= end; i++)
		{
			const WTSBarStruct& day = *at(i);
			switch (type)
			{
			case KFT_OPEN:
				vArray->append(day.open);
				break;
			case KFT_HIGH:
				vArray->append(day.high);
				break;
			case KFT_LOW:
				vArray->append(day.low);
				break;
			case KFT_CLOSE:
				vArray->append(day.close);
				break;
			case KFT_VOLUME:
				vArray->append(day.vol);
				break;
			case KFT_SVOLUME:
				if (day.vol > INT_MAX)
					vArray->append(1 * ((day.close > day.open) ? 1 : -1));
				else
					vArray->append((int32_t)day.vol * ((day.close > day.open) ? 1 : -1));
				break;
			case KFT_DATE:
				vArray->append(day.date);
				break;
			}
		}

		return vArray;
	}
};

/*!
 * \brief K线数据容器类
 * \details 完整的K线数据管理容器，基于std::vector实现，提供丰富的K线数据操作接口。
 *          相比WTSKlineSlice的分块管理方式，本类采用连续内存存储，适合小到中等规模的K线数据。
 *          
 *          核心特性：
 *          - 连续内存存储：基于std::vector的高效内存管理
 *          - 多周期支持：可设置任意基础周期和倍数组合
 *          - 丰富的访问接口：提供按字段、按索引的多种访问方式
 *          - 数据提取功能：支持字段数据的批量提取
 *          - 统计查询：内置最高价、最低价查询功能
 *          - 时间戳支持：支持Unix时间戳格式（秒级数据）
 *          
 *          适用场景：
 *          - 策略中的K线数据缓存
 *          - 技术指标计算的数据源
 *          - 小到中等规模的历史数据存储
 *          - 实时K线数据的动态管理
 */
class WTSKlineData : public WTSObject
{
public:
	typedef std::vector<WTSBarStruct> WTSBarList;

protected:
	char			m_strCode[32];
	WTSKlinePeriod	m_kpPeriod;
	uint32_t		m_uTimes;
	bool			m_bUnixTime;	//是否是时间戳格式,目前只在秒线上有效
	WTSBarList		m_vecBarData;
	bool			m_bClosed;		//是否是闭合K线

protected:
	WTSKlineData()
		:m_kpPeriod(KP_Minute1)
		,m_uTimes(1)
		,m_bUnixTime(false)
		,m_bClosed(true)
	{

	}

	inline int32_t		translateIdx(int32_t idx) const
	{
		if(idx < 0)
		{
			return max(0, (int32_t)m_vecBarData.size() + idx);
		}

		return idx;
	}

public:
	/*!
	 * \brief 创建K线数据对象
	 * \details 工厂方法，创建指定合约和容量的K线数据容器。
	 * \param code 合约代码
	 * \param size 初始分配的K线条数，容器会预先分配对应的内存空间
	 * \return WTSKlineData* 新创建的K线数据对象指针
	 */
	static WTSKlineData* create(const char* code, uint32_t size)
	{
		WTSKlineData *pRet = new WTSKlineData;
		pRet->m_vecBarData.resize(size);
		wt_strcpy(pRet->m_strCode, code);

		return pRet;
	}

	/*!
	 * \brief 设置K线是否已闭合
	 * \param bClosed true表示K线已闭合，false表示K线未闭合（正在形成中）
	 */
	inline void setClosed(bool bClosed){ m_bClosed = bClosed; }
	
	/*!
	 * \brief 获取K线闭合状态
	 * \return bool true表示K线已闭合，false表示K线未闭合
	 */
	inline bool isClosed() const{ return m_bClosed; }

	/*!
	 * \brief 设置K线周期
	 * \param period 基础周期类型（分钟、小时、日等）
	 * \param times 周期倍数，默认为1
	 */
	inline void	setPeriod(WTSKlinePeriod period, uint32_t times = 1){ m_kpPeriod = period; m_uTimes = times; }

	/*!
	 * \brief 设置时间戳格式
	 * \param bEnabled true使用Unix时间戳格式，false使用传统格式
	 */
	inline void	setUnixTime(bool bEnabled = true){ m_bUnixTime = bEnabled; }

	/*!
	 * \brief 获取K线周期类型
	 * \return WTSKlinePeriod K线基础周期
	 */
	inline WTSKlinePeriod	period() const{ return m_kpPeriod; }
	
	/*!
	 * \brief 获取周期倍数
	 * \return uint32_t 周期倍数
	 */
	inline uint32_t		times() const{ return m_uTimes; }
	
	/*!
	 * \brief 获取时间戳格式
	 * \return bool true表示使用Unix时间戳，false表示使用传统格式
	 */
	inline bool			isUnixTime() const{ return m_bUnixTime; }

	/*!
	 * \brief 查找指定范围内的最高价
	 * \details 在给定的索引范围内查找最高价格，支持负索引。
	 * \param head 起始索引（支持负值）
	 * \param tail 结束索引（支持负值）
	 * \return double 范围内的最高价，超出范围时返回INVALID_DOUBLE
	 */
	inline double		maxprice(int32_t head, int32_t tail) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		uint32_t begin = min(head, tail);
		uint32_t end = max(head, tail);

		if(begin >= m_vecBarData.size() || end > m_vecBarData.size())
			return INVALID_DOUBLE;

		double maxValue = m_vecBarData[begin].high;
		for(uint32_t i = begin; i <= end; i++)
		{
			maxValue = max(maxValue, m_vecBarData[i].high);
		}

		return maxValue;
	}

	/*!
	 * \brief 查找指定范围内的最低价
	 * \details 在给定的索引范围内查找最低价格，支持负索引。
	 * \param head 起始索引（支持负值）
	 * \param tail 结束索引（支持负值）
	 * \return double 范围内的最低价，超出范围时返回INVALID_DOUBLE
	 */
	inline double		minprice(int32_t head, int32_t tail) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		uint32_t begin = min(head, tail);
		uint32_t end = max(head, tail);

		if(begin >= m_vecBarData.size() || end > m_vecBarData.size())
			return INVALID_DOUBLE;

		double minValue = m_vecBarData[begin].low;
		for(uint32_t i = begin; i <= end; i++)
		{
			minValue = min(minValue, m_vecBarData[i].low);
		}

		return minValue;
	}
	
	/*!
	 * \brief 获取K线数据条数
	 * \return uint32_t K线数据的总条数
	 */
	inline uint32_t	size() const{return m_vecBarData.size();}
	
	/*!
	 * \brief 检查K线数据是否为空
	 * \return bool true表示无K线数据，false表示包含数据
	 */
	inline bool IsEmpty() const{ return m_vecBarData.empty(); }

	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串指针
	 */
	inline const char*	code() const{ return m_strCode; }
	
	/*!
	 * \brief 设置合约代码
	 * \param code 合约代码字符串
	 */
	inline void		setCode(const char* code){ wt_strcpy(m_strCode, code); }

	/*!
	 * \brief 获取指定位置的开盘价
	 * \details 支持负索引访问，-1表示最后一条K线的开盘价。
	 * \param idx K线索引位置
	 * \return double 开盘价，索引无效时返回INVALID_DOUBLE
	 */
	inline double	open(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].open;
	}

	/*!
	 * \brief 获取指定位置的最高价
	 * \details 支持负索引访问，-1表示最后一条K线的最高价。
	 * \param idx K线索引位置
	 * \return double 最高价，索引无效时返回INVALID_DOUBLE
	 */
	inline double	high(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].high;
	}

	/*!
	 * \brief 获取指定位置的最低价
	 * \details 支持负索引访问，-1表示最后一条K线的最低价。
	 * \param idx K线索引位置
	 * \return double 最低价，索引无效时返回INVALID_DOUBLE
	 */
	inline double	low(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].low;
	}

	/*!
	 * \brief 获取指定位置的收盘价
	 * \details 支持负索引访问，-1表示最后一条K线的收盘价。
	 * \param idx K线索引位置
	 * \return double 收盘价，索引无效时返回INVALID_DOUBLE
	 */
	inline double	close(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].close;
	}

	/*!
	 * \brief 获取指定位置的成交量
	 * \details 支持负索引访问，-1表示最后一条K线的成交量。
	 * \param idx K线索引位置
	 * \return double 成交量，索引无效时返回INVALID_DOUBLE
	 */
	inline double	volume(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].vol;
	}

	/*!
	 * \brief 获取指定位置的持仓量
	 * \details 支持负索引访问，-1表示最后一条K线的持仓量。主要用于期货合约。
	 * \param idx K线索引位置
	 * \return double 持仓量，索引无效时返回INVALID_UINT32
	 */
	inline double	openinterest(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_UINT32;

		return m_vecBarData[idx].hold;
	}

	/*!
	 * \brief 获取指定位置的增仓量
	 * \details 支持负索引访问，-1表示最后一条K线的增仓量。表示持仓量相对前一周期的变化。
	 * \param idx K线索引位置
	 * \return double 增仓量，索引无效时返回INVALID_DOUBLE
	 */
	inline double	additional(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].add;
	}	

	/*!
	 * \brief 获取指定位置的成交额
	 * \details 支持负索引访问，-1表示最后一条K线的成交额。
	 * \param idx K线索引位置
	 * \return double 成交额，索引无效时返回INVALID_DOUBLE
	 */
	inline double	money(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_DOUBLE;

		return m_vecBarData[idx].money;
	}

	/*!
	 * \brief 获取指定位置的日期
	 * \details 支持负索引访问，-1表示最后一条K线的日期。
	 * \param idx K线索引位置
	 * \return uint32_t 日期（YYYYMMDD格式），索引无效时返回INVALID_UINT32
	 */
	inline uint32_t	date(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_UINT32;

		return m_vecBarData[idx].date;
	}

	/*!
	 * \brief 获取指定位置的时间
	 * \details 支持负索引访问，-1表示最后一条K线的时间。时间格式取决于isUnixTime()设置。
	 * \param idx K线索引位置
	 * \return uint64_t 时间值，索引无效时返回INVALID_UINT32
	 */
	inline uint64_t	time(int32_t idx) const
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return INVALID_UINT32;

		return m_vecBarData[idx].time;
	}

	/*!
	 * \brief 提取K线字段数据
	 * \details 从指定范围的K线数据中提取特定字段，生成数值数组。
	 *          常用于技术指标计算和数据分析，支持各种K线数据字段的批量提取。
	 * \param type 字段类型，支持以下类型：
	 *             - KFT_OPEN: 开盘价
	 *             - KFT_HIGH: 最高价
	 *             - KFT_LOW: 最低价
	 *             - KFT_CLOSE: 收盘价
	 *             - KFT_VOLUME: 成交量
	 *             - KFT_SVOLUME: 带符号成交量（上涨为正，下跌为负）
	 *             - KFT_DATE: 日期
	 * \param head 起始索引，默认为0，支持负值
	 * \param tail 结束索引，默认为-1（表示最后一条），支持负值
	 * \return WTSValueArray* 包含提取数据的数值数组，范围无效或无数据时返回NULL
	 */
	WTSValueArray*	extractData(WTSKlineFieldType type, int32_t head = 0, int32_t tail = -1) const
	{
		head = translateIdx(head);
		tail = translateIdx(tail);

		uint32_t begin = min(head, tail);
		uint32_t end = max(head, tail);

		if(begin >= m_vecBarData.size() || end >= (int32_t)m_vecBarData.size())
			return NULL;

		WTSValueArray *vArray = NULL;

		vArray = WTSValueArray::create();

		for(uint32_t i = 0; i < m_vecBarData.size(); i++)
		{
			const WTSBarStruct& day = m_vecBarData.at(i);
			switch(type)
			{
			case KFT_OPEN:
				vArray->append(day.open);
				break;
			case KFT_HIGH:
				vArray->append(day.high);
				break;
			case KFT_LOW:
				vArray->append(day.low);
				break;
			case KFT_CLOSE:
				vArray->append(day.close);
				break;
			case KFT_VOLUME:
				vArray->append(day.vol);
				break;
			case KFT_SVOLUME:
				if(day.vol > INT_MAX)
					vArray->append(1 * ((day.close > day.open) ? 1 : -1));
				else
					vArray->append((int32_t)day.vol * ((day.close > day.open)?1:-1));
				break;
			case KFT_DATE:
				vArray->append(day.date);
				break;
			}
		}

		return vArray;
	}

public:
	/*!
	 * \brief 获取K线数据容器引用
	 * \details 返回内部std::vector<WTSBarStruct>的直接引用，用于高效的批量操作。
	 * \return WTSBarList& 底层K线数据容器的引用
	 * \warning 直接操作底层容器可能破坏对象状态，请谨慎使用
	 */
	inline WTSBarList& getDataRef(){ return m_vecBarData; }

	/*!
	 * \brief 获取指定位置的K线数据
	 * \details 支持负索引访问，-1表示最后一条K线。
	 * \param idx K线索引位置
	 * \return WTSBarStruct* K线数据结构指针，索引无效时返回NULL
	 */
	inline WTSBarStruct*	at(int32_t idx)
	{
		idx = translateIdx(idx);

		if(idx < 0 || idx >= (int32_t)m_vecBarData.size())
			return NULL;
		return &m_vecBarData[idx];
	}

	/*!
	 * \brief 释放K线数据
	 * \details 清空内部K线数据容器，释放相关内存资源。
	 *          只有在对象引用计数为1时才会真正清空数据。
	 */
	virtual void release()
	{
		if(isSingleRefs())
		{
			m_vecBarData.clear();
		}		

		WTSObject::release();
	}

	/*!
	 * \brief 追加一条K线数据
	 * \details 智能追加K线数据，如果新K线的日期时间与最后一条相同，则更新最后一条；
	 *          否则添加新的K线数据。这种机制适用于实时K线数据的动态更新。
	 * \param bar K线数据结构体
	 */
	inline void	appendBar(const WTSBarStruct& bar)
	{
		if(m_vecBarData.empty())
		{
			m_vecBarData.emplace_back(bar);
		}
		else
		{
			WTSBarStruct* lastBar = at(-1);
			if(lastBar->date==bar.date && lastBar->time==bar.time)
			{
				memcpy(lastBar, &bar, sizeof(WTSBarStruct));
			}
			else
			{
				m_vecBarData.emplace_back(bar);
			}
		}
	}
};



/*!
 * \brief Tick行情数据对象
 * \details 逐笔行情数据的封装类，基于对象池管理以提高性能。
 *          包含完整的市场快照信息，包括价格、量、买卖盘等详细数据。
 *          
 *          主要特性：
 *          - 对象池管理：基于WTSPoolObject的高效内存管理
 *          - 完整行情数据：价格、成交量、买卖盘、时间等全部信息
 *          - 十档行情支持：支持深度行情的买卖盘数据
 *          - 多市场兼容：支持股票、期货、期权等多种市场
 *          - 跨语言支持：设计便于与其他语言交互
 */
class WTSTickData : public WTSPoolObject<WTSTickData>
{
public:
	WTSTickData() :m_pContract(NULL) {}

	/*
	 *	创建一个tick数据对象
	 *	@stdCode 合约代码
	 */
	static inline WTSTickData* create(const char* stdCode)
	{
		WTSTickData* pRet = WTSTickData::allocate();
		auto len = strlen(stdCode);
		memcpy(pRet->m_tickStruct.code, stdCode, len);
		pRet->m_tickStruct.code[len] = 0;

		return pRet;
	}

	/*
	 *	根据tick结构体创建一个tick数据对象
	 *	@tickData tick结构体
	 */
	static inline WTSTickData* create(WTSTickStruct& tickData)
	{
		WTSTickData* pRet = allocate();
		memcpy(&pRet->m_tickStruct, &tickData, sizeof(WTSTickStruct));

		return pRet;
	}

	inline void setCode(const char* code, std::size_t len = 0)
	{
		len = (len == 0) ? strlen(code) : len;

		memcpy(m_tickStruct.code, code, len);
		m_tickStruct.code[len] = '\0';
	}

	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串
	 */
	inline const char* code() const{ return m_tickStruct.code; }

	/*!
	 * \brief 获取交易所代码
	 * \return const char* 交易所代码字符串
	 */
	inline const char*	exchg() const{ return m_tickStruct.exchg; }

	/*!
	 * \brief 获取最新价格
	 * \return double 当前最新成交价格
	 */
	inline double	price() const{ return m_tickStruct.price; }

	/*!
	 * \brief 获取开盘价格
	 * \return double 当日开盘价格
	 */
	inline double	open() const{ return m_tickStruct.open; }

	/*!
	 * \brief 获取最高价格
	 * \return double 当日最高成交价格
	 */
	inline double	high() const{ return m_tickStruct.high; }

	/*!
	 * \brief 获取最低价格
	 * \return double 当日最低成交价格
	 */
	inline double	low() const{ return m_tickStruct.low; }

	/*!
	 * \brief 获取昨收盘价
	 * \details 对于股票返回昨收盘价，对于期货返回昨结算价
	 * \return double 昨收盘价格
	 */
	inline double	preclose() const{ return m_tickStruct.pre_close; }
	
	/*!
	 * \brief 获取昨结算价
	 * \return double 昨日结算价格
	 */
	inline double	presettle() const{ return m_tickStruct.pre_settle; }
	
	/*!
	 * \brief 获取昨持仓量
	 * \return double 昨日持仓量
	 */
	inline double	preinterest() const{ return m_tickStruct.pre_interest; }

	/*!
	 * \brief 获取涨停价
	 * \return double 当日涨停价格
	 */
	inline double	upperlimit() const{ return m_tickStruct.upper_limit; }
	
	/*!
	 * \brief 获取跌停价
	 * \return double 当日跌停价格
	 */
	inline double	lowerlimit() const{ return m_tickStruct.lower_limit; }
	
	/*!
	 * \brief 获取累计成交量
	 * \return double 从开盘到当前的累计成交量
	 */
	inline double	totalvolume() const{ return m_tickStruct.total_volume; }

	/*!
	 * \brief 获取当前成交量
	 * \return double 当前Tick的成交量
	 */
	inline double	volume() const{ return m_tickStruct.volume; }

	/*!
	 * \brief 获取结算价
	 * \return double 当日结算价格
	 */
	inline double	settlepx() const{ return m_tickStruct.settle_price; }

	/*!
	 * \brief 获取持仓量
	 * \return double 当前持仓量
	 */
	inline double	openinterest() const{ return m_tickStruct.open_interest; }

	/*!
	 * \brief 获取持仓量变化
	 * \return double 持仓量相对前一Tick的变化量
	 */
	inline double	additional() const{ return m_tickStruct.diff_interest; }

	/*!
	 * \brief 获取累计成交额
	 * \return double 从开盘到当前的累计成交金额
	 */
	inline double	totalturnover() const{ return m_tickStruct.total_turnover; }

	/*!
	 * \brief 获取当前成交额
	 * \return double 当前Tick的成交金额
	 */
	inline double	turnover() const{ return m_tickStruct.turn_over; }

	/*!
	 * \brief 获取交易日期
	 * \return uint32_t 交易日期（YYYYMMDD格式）
	 */
	inline uint32_t	tradingdate() const{ return m_tickStruct.trading_date; }

	/*!
	 * \brief 获取数据发生日期
	 * \return uint32_t 数据产生的自然日期（YYYYMMDD格式）
	 */
	inline uint32_t	actiondate() const{ return m_tickStruct.action_date; }

	/*!
	 * \brief 获取数据发生时间
	 * \return uint32_t 数据产生的具体时间（毫秒精度）
	 */
	inline uint32_t	actiontime() const{ return m_tickStruct.action_time; }


	/*!
	 * \brief 获取指定档位的委买价格
	 * \details 获取买盘指定档位的委托价格，支持十档深度行情。
	 * \param idx 档位索引，范围0-9（0为最优买价）
	 * \return double 指定档位的委买价格，索引无效时返回-1
	 */
	inline double		bidprice(int idx) const
	{
		if(idx < 0 || idx >= 10) 
			return -1;

		return m_tickStruct.bid_prices[idx];
	}

	/*!
	 * \brief 获取指定档位的委卖价格
	 * \details 获取卖盘指定档位的委托价格，支持十档深度行情。
	 * \param idx 档位索引，范围0-9（0为最优卖价）
	 * \return double 指定档位的委卖价格，索引无效时返回-1
	 */
	inline double		askprice(int idx) const
	{
		if(idx < 0 || idx >= 10) 
			return -1;

		return m_tickStruct.ask_prices[idx];
	}

	/*!
	 * \brief 获取指定档位的委买数量
	 * \details 获取买盘指定档位的委托数量，支持十档深度行情。
	 * \param idx 档位索引，范围0-9（0为最优买价对应数量）
	 * \return double 指定档位的委买数量，索引无效时返回-1
	 */
	inline double	bidqty(int idx) const
	{
		if(idx < 0 || idx >= 10) 
			return -1;

		return m_tickStruct.bid_qty[idx];
	}

	/*!
	 * \brief 获取指定档位的委卖数量
	 * \details 获取卖盘指定档位的委托数量，支持十档深度行情。
	 * \param idx 档位索引，范围0-9（0为最优卖价对应数量）
	 * \return double 指定档位的委卖数量，索引无效时返回-1
	 */
	inline double	askqty(int idx) const
	{
		if(idx < 0 || idx >= 10) 
			return -1;

		return m_tickStruct.ask_qty[idx];
	}

	/*!
	 * \brief 获取底层Tick结构体引用
	 * \details 返回内部WTSTickStruct结构体的直接引用，用于高效的底层数据操作。
	 * \return WTSTickStruct& Tick数据结构体的引用
	 * \warning 直接操作底层结构体可能破坏对象状态，请谨慎使用
	 */
	inline WTSTickStruct&	getTickStruct(){ return m_tickStruct; }

	/*!
	 * \brief 设置合约信息
	 * \param cInfo 合约信息对象指针
	 */
	inline void setContractInfo(WTSContractInfo* cInfo) { m_pContract = cInfo; }
	
	/*!
	 * \brief 获取合约信息
	 * \return WTSContractInfo* 合约信息对象指针
	 */
	inline WTSContractInfo* getContractInfo() const { return m_pContract; }

private:
	WTSTickStruct		m_tickStruct;
	WTSContractInfo*	m_pContract;
};

/*!
 * \brief 委托队列数据类
 * \details Level2市场深度委托队列数据的封装类，提供详细的市场委托队列信息。
 *          包含买卖双方的委托队列详情，用于高频交易和市场微观结构分析。
 *          
 *          主要功能：
 *          - 委托队列快照：记录特定时刻的委托队列状态
 *          - 深度信息：提供比五档行情更详细的市场深度
 *          - 时间戳信息：精确的数据生成和接收时间
 *          - 交易所兼容：支持多个交易所的队列数据格式
 */
class WTSOrdQueData : public WTSObject
{
public:
	/*!
	 * \brief 创建委托队列数据对象
	 * \param code 合约代码
	 * \return WTSOrdQueData* 新创建的委托队列数据对象指针
	 */
	static inline WTSOrdQueData* create(const char* code)
	{
		WTSOrdQueData* pRet = new WTSOrdQueData;
		wt_strcpy(pRet->m_oqStruct.code, code);
		return pRet;
	}

	/*!
	 * \brief 根据委托队列结构体创建数据对象
	 * \param ordQueData 委托队列结构体引用
	 * \return WTSOrdQueData* 新创建的委托队列数据对象指针
	 */
	static inline WTSOrdQueData* create(WTSOrdQueStruct& ordQueData)
	{
		WTSOrdQueData* pRet = new WTSOrdQueData;
		memcpy(&pRet->m_oqStruct, &ordQueData, sizeof(WTSOrdQueStruct));

		return pRet;
	}

	/*!
	 * \brief 获取底层委托队列结构体引用
	 * \return WTSOrdQueStruct& 委托队列结构体的引用
	 */
	inline WTSOrdQueStruct& getOrdQueStruct(){return m_oqStruct;}

	/*!
	 * \brief 获取交易所代码
	 * \return const char* 交易所代码字符串
	 */
	inline const char* exchg() const{ return m_oqStruct.exchg; }
	
	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串
	 */
	inline const char* code() const{ return m_oqStruct.code; }
	
	/*!
	 * \brief 获取交易日期
	 * \return uint32_t 交易日期（YYYYMMDD格式）
	 */
	inline uint32_t tradingdate() const{ return m_oqStruct.trading_date; }
	
	/*!
	 * \brief 获取数据发生日期
	 * \return uint32_t 数据发生日期（YYYYMMDD格式）
	 */
	inline uint32_t actiondate() const{ return m_oqStruct.action_date; }
	
	/*!
	 * \brief 获取数据发生时间
	 * \return uint32_t 数据发生时间（毫秒精度）
	 */
	inline uint32_t actiontime() const { return m_oqStruct.action_time; }

	/*!
	 * \brief 设置合约代码
	 * \param code 合约代码字符串
	 */
	inline void		setCode(const char* code) { wt_strcpy(m_oqStruct.code, code); }

private:
	WTSOrdQueStruct	m_oqStruct;
};

/*!
 * \brief 委托明细数据类
 * \details Level2市场深度委托明细数据的封装类，提供逐笔委托的详细信息。
 *          记录每一笔委托的具体信息，用于市场微观结构分析和订单流研究。
 *          
 *          主要功能：
 *          - 逐笔委托记录：每个委托的详细信息
 *          - 委托属性：买卖方向、价格、数量等详细信息
 *          - 时序数据：精确的委托提交时间戳
 *          - 市场分析：支持委托流分析和市场行为研究
 */
class WTSOrdDtlData : public WTSObject
{
public:
	/*!
	 * \brief 创建委托明细数据对象
	 * \param code 合约代码
	 * \return WTSOrdDtlData* 新创建的委托明细数据对象指针
	 */
	static inline WTSOrdDtlData* create(const char* code)
	{
		WTSOrdDtlData* pRet = new WTSOrdDtlData;
		wt_strcpy(pRet->m_odStruct.code, code);
		return pRet;
	}

	/*!
	 * \brief 根据委托明细结构体创建数据对象
	 * \param odData 委托明细结构体引用
	 * \return WTSOrdDtlData* 新创建的委托明细数据对象指针
	 */
	static inline WTSOrdDtlData* create(WTSOrdDtlStruct& odData)
	{
		WTSOrdDtlData* pRet = new WTSOrdDtlData;
		memcpy(&pRet->m_odStruct, &odData, sizeof(WTSOrdDtlStruct));

		return pRet;
	}

	/*!
	 * \brief 获取底层委托明细结构体引用
	 * \return WTSOrdDtlStruct& 委托明细结构体的引用
	 */
	inline WTSOrdDtlStruct& getOrdDtlStruct(){ return m_odStruct; }

	/*!
	 * \brief 获取交易所代码
	 * \return const char* 交易所代码字符串
	 */
	inline const char* exchg() const{ return m_odStruct.exchg; }
	
	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串
	 */
	inline const char* code() const{ return m_odStruct.code; }
	
	/*!
	 * \brief 获取交易日期
	 * \return uint32_t 交易日期（YYYYMMDD格式）
	 */
	inline uint32_t tradingdate() const{ return m_odStruct.trading_date; }
	
	/*!
	 * \brief 获取数据发生日期
	 * \return uint32_t 数据发生日期（YYYYMMDD格式）
	 */
	inline uint32_t actiondate() const{ return m_odStruct.action_date; }
	
	/*!
	 * \brief 获取数据发生时间
	 * \return uint32_t 数据发生时间（毫秒精度）
	 */
	inline uint32_t actiontime() const { return m_odStruct.action_time; }

	/*!
	 * \brief 设置合约代码
	 * \param code 合约代码字符串
	 */
	inline void		setCode(const char* code) { wt_strcpy(m_odStruct.code, code); }

private:
	WTSOrdDtlStruct	m_odStruct;
};

/*!
 * \brief 成交明细数据类
 * \details Level2市场成交明细数据的封装类，提供逐笔成交的详细信息。
 *          记录每一笔真实成交的具体信息，用于成交量分析和价格发现研究。
 *          
 *          主要功能：
 *          - 逐笔成交记录：每个成交的详细信息
 *          - 成交属性：成交价格、成交量、买卖方向等
 *          - 实时数据：精确的成交时间戳信息
 *          - 交易分析：支持成交流分析和价格变动研究
 */
class WTSTransData : public WTSObject
{
public:
	/*!
	 * \brief 创建成交明细数据对象
	 * \param code 合约代码
	 * \return WTSTransData* 新创建的成交明细数据对象指针
	 */
	static inline WTSTransData* create(const char* code)
	{
		WTSTransData* pRet = new WTSTransData;
		wt_strcpy(pRet->m_tsStruct.code, code);
		return pRet;
	}

	/*!
	 * \brief 根据成交明细结构体创建数据对象
	 * \param transData 成交明细结构体引用
	 * \return WTSTransData* 新创建的成交明细数据对象指针
	 */
	static inline WTSTransData* create(WTSTransStruct& transData)
	{
		WTSTransData* pRet = new WTSTransData;
		memcpy(&pRet->m_tsStruct, &transData, sizeof(WTSTransStruct));

		return pRet;
	}

	/*!
	 * \brief 获取交易所代码
	 * \return const char* 交易所代码字符串
	 */
	inline const char* exchg() const{ return m_tsStruct.exchg; }
	
	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串
	 */
	inline const char* code() const{ return m_tsStruct.code; }
	
	/*!
	 * \brief 获取交易日期
	 * \return uint32_t 交易日期（YYYYMMDD格式）
	 */
	inline uint32_t tradingdate() const{ return m_tsStruct.trading_date; }
	
	/*!
	 * \brief 获取数据发生日期
	 * \return uint32_t 数据发生日期（YYYYMMDD格式）
	 */
	inline uint32_t actiondate() const{ return m_tsStruct.action_date; }
	
	/*!
	 * \brief 获取数据发生时间
	 * \return uint32_t 数据发生时间（毫秒精度）
	 */
	inline uint32_t actiontime() const { return m_tsStruct.action_time; }

	/*!
	 * \brief 获取底层成交明细结构体引用
	 * \return WTSTransStruct& 成交明细结构体的引用
	 */
	inline WTSTransStruct& getTransStruct(){ return m_tsStruct; }

	/*!
	 * \brief 设置合约代码
	 * \param code 合约代码字符串
	 */
	inline void		setCode(const char* code) { wt_strcpy(m_tsStruct.code, code); }

private:
	WTSTransStruct	m_tsStruct;
};

/*!
 * \brief 历史Tick数据容器类
 * \details 用于存储和管理历史Tick行情数据的容器类，基于std::vector实现。
 *          支持复权处理、数据有效性过滤等高级功能，适用于历史数据回放和策略回测。
 *          
 *          主要特性：
 *          - 批量存储：高效存储大量历史Tick数据
 *          - 复权支持：自动进行除权除息调整
 *          - 数据过滤：支持有效数据筛选功能
 *          - 随机访问：提供快速的索引访问
 *          - 内存优化：采用连续内存存储提高性能
 */
class WTSHisTickData : public WTSObject
{
protected:
	char						m_strCode[32];
	std::vector<WTSTickStruct>	m_ayTicks;
	bool						m_bValidOnly;
	double						m_dFactor;

	WTSHisTickData() :m_bValidOnly(false), m_dFactor(1.0){}

public:
	/*!
	 * \brief 创建指定容量的历史Tick数据对象
	 * \details 工厂方法，创建具有预分配容量的历史Tick数据容器。
	 * \param stdCode 标准合约代码
	 * \param nSize 预分配的容量大小，0表示不预分配
	 * \param bValidOnly 是否只保留有效数据，默认false
	 * \param factor 复权因子，用于价格调整，默认1.0（不调整）
	 * \return WTSHisTickData* 新创建的历史Tick数据对象指针
	 */
	static inline WTSHisTickData* create(const char* stdCode, unsigned int nSize = 0, bool bValidOnly = false, double factor = 1.0)
	{
		WTSHisTickData *pRet = new WTSHisTickData;
		wt_strcpy(pRet->m_strCode, stdCode);
		pRet->m_ayTicks.resize(nSize);
		pRet->m_bValidOnly = bValidOnly;
		pRet->m_dFactor = factor;

		return pRet;
	}

	/*!
	 * \brief 创建历史Tick数据对象（动态容量）
	 * \details 工厂方法，创建动态增长的历史Tick数据容器。
	 * \param stdCode 标准合约代码
	 * \param bValidOnly 是否只保留有效数据，默认false
	 * \param factor 复权因子，用于价格调整，默认1.0（不调整）
	 * \return WTSHisTickData* 新创建的历史Tick数据对象指针
	 */
	static inline WTSHisTickData* create(const char* stdCode, bool bValidOnly = false, double factor = 1.0)
	{
		WTSHisTickData *pRet = new WTSHisTickData;
		wt_strcpy(pRet->m_strCode, stdCode);
		pRet->m_bValidOnly = bValidOnly;
		pRet->m_dFactor = factor;

		return pRet;
	}

	/*!
	 * \brief 获取Tick数据条数
	 * \return uint32_t 容器中Tick数据的总条数
	 */
	inline uint32_t	size() const{ return m_ayTicks.size(); }
	
	/*!
	 * \brief 检查容器是否为空
	 * \return bool true表示容器为空，false表示包含数据
	 */
	inline bool		empty() const{ return m_ayTicks.empty(); }

	/*!
	 * \brief 获取合约代码
	 * \return const char* 合约代码字符串指针
	 */
	inline const char*		code() const{ return m_strCode; }

	/*!
	 * \brief 获取指定位置的Tick数据
	 * \details 提供随机访问指定索引位置的Tick数据。
	 * \param idx 数据索引位置
	 * \return WTSTickStruct* Tick数据结构指针，索引无效时返回NULL
	 */
	inline WTSTickStruct*	at(uint32_t idx)
	{
		if (m_ayTicks.empty() || idx >= m_ayTicks.size())
			return NULL;

		return &m_ayTicks[idx];
	}

	/*!
	 * \brief 获取底层数据容器的引用
	 * \details 返回内部std::vector<WTSTickStruct>的直接引用，用于高效的批量操作。
	 * \return std::vector<WTSTickStruct>& 底层数据容器的引用
	 * \warning 直接操作底层容器可能破坏对象状态，请谨慎使用
	 */
	inline std::vector<WTSTickStruct>& getDataRef() { return m_ayTicks; }

	/*!
	 * \brief 获取数据过滤模式
	 * \return bool true表示只保留有效数据，false表示保留所有数据
	 */
	inline bool isValidOnly() const{ return m_bValidOnly; }

	/*!
	 * \brief 追加一条Tick数据
	 * \details 在容器末尾添加新的Tick数据，自动应用复权因子进行价格调整。
	 * \param ts Tick数据结构体引用
	 */
	inline void	appendTick(const WTSTickStruct& ts)
	{
		m_ayTicks.emplace_back(ts);
		//复权修正
		m_ayTicks.back().price *= m_dFactor;
		m_ayTicks.back().open *= m_dFactor;
		m_ayTicks.back().high *= m_dFactor;
		m_ayTicks.back().low *= m_dFactor;
	}
};

//////////////////////////////////////////////////////////////////////////
/*!
 * \brief Tick数据切片类
 * \details 高性能的Tick数据切片管理器，基于分块存储实现。
 *          切片不复制内存，而是通过索引范围管理多个数据块，提供统一的访问接口。
 *          适用于大量Tick数据的高效管理和访问。
 *          
 *          核心特性：
 *          - 零拷贝设计：不复制数据，只管理引用和索引
 *          - 分块管理：支持多个不连续的数据块
 *          - 统一访问：提供连续的逻辑索引访问
 *          - 高效插入：支持数据块的动态添加和插入
 *          - 内存友好：避免大量数据的重复拷贝
 *          
 *          注意事项：
 *          - 依赖于底层数据对象的生命周期
 *          - 切片对象不拥有数据的所有权
 *          - 使用时需确保底层数据的有效性
 */
class WTSTickSlice : public WTSObject
{
private:
	char			_code[MAX_INSTRUMENT_LENGTH];
	typedef std::pair<WTSTickStruct*, uint32_t> TickBlock;
	std::vector<TickBlock> _blocks;
	uint32_t		_count;

protected:
	WTSTickSlice(){}
	inline int32_t		translateIdx(int32_t idx) const
	{
		if (idx < 0)
		{
			return max(0, (int32_t)_count + idx);
		}

		return idx;
	}

public:
	/*!
	 * \brief 创建Tick数据切片对象
	 * \details 工厂方法，创建一个新的WTSTickSlice实例。可选择性地添加初始数据块。
	 * \param code 合约代码
	 * \param ticks 初始Tick数据指针，可为NULL
	 * \param count 初始数据条数，ticks为NULL时应为0
	 * \return WTSTickSlice* 新创建的Tick切片对象指针，参数无效时返回NULL
	 */
	static inline WTSTickSlice* create(const char* code, WTSTickStruct* ticks = NULL, uint32_t count = 0)
	{
		if (ticks == NULL || count == 0)
			return NULL;

		WTSTickSlice* slice = new WTSTickSlice();
		wt_strcpy(slice->_code, code);
		if(ticks != NULL)
		{
			slice->_blocks.emplace_back(TickBlock(ticks, count));
			slice->_count = count;
		}

		return slice;
	}

	/*!
	 * \brief 追加数据块
	 * \details 在切片末尾添加新的Tick数据块，用于动态扩展数据。
	 * \param ticks Tick数据指针，不能为NULL
	 * \param count 数据条数，必须大于0
	 * \return bool 成功返回true，参数无效返回false
	 */
	inline bool appendBlock(WTSTickStruct* ticks, uint32_t count)
	{
		if (ticks == NULL || count == 0)
			return false;

		_count += count;
		_blocks.emplace_back(TickBlock(ticks, count));
		return true;
	}

	/*!
	 * \brief 插入数据块
	 * \details 在指定位置插入新的Tick数据块。
	 * \param idx 插入位置索引
	 * \param ticks Tick数据指针，不能为NULL
	 * \param count 数据条数，必须大于0
	 * \return bool 成功返回true，参数无效返回false
	 */
	inline bool insertBlock(std::size_t idx, WTSTickStruct* ticks, uint32_t count)
	{
		if (ticks == NULL || count == 0)
			return false;

		_count += count;
		_blocks.insert(_blocks.begin()+idx, TickBlock(ticks, count));
		return true;
	}

	/*!
	 * \brief 获取数据块数量
	 * \return std::size_t 切片中数据块的总数
	 */
	inline std::size_t	get_block_counts() const
	{
		return _blocks.size();
	}

	/*!
	 * \brief 获取指定数据块的地址
	 * \param blkIdx 数据块索引
	 * \return WTSTickStruct* 数据块起始地址，索引无效时返回NULL
	 */
	inline WTSTickStruct*	get_block_addr(std::size_t blkIdx)
	{
		if (blkIdx >= _blocks.size())
			return NULL;

		return _blocks[blkIdx].first;
	}

	/*!
	 * \brief 获取指定数据块的大小
	 * \param blkIdx 数据块索引
	 * \return uint32_t 数据块包含的Tick条数，索引无效时返回INVALID_UINT32
	 */
	inline uint32_t get_block_size(std::size_t blkIdx)
	{
		if (blkIdx >= _blocks.size())
			return INVALID_UINT32;

		return _blocks[blkIdx].second;
	}

	/*!
	 * \brief 获取Tick数据总条数
	 * \return uint32_t 所有数据块中的Tick总数
	 */
	inline uint32_t size() const{ return _count; }

	/*!
	 * \brief 检查切片是否为空
	 * \return bool true表示无Tick数据，false表示包含数据
	 */
	inline bool empty() const{ return (_count == 0); }

	/*!
	 * \brief 获取指定位置的Tick数据
	 * \details 通过统一索引访问分块存储的Tick数据，支持负索引从末尾倒数。
	 *          内部自动定位到对应的数据块并返回具体位置的指针。
	 * \param idx 数据索引，支持负值（-1表示最后一条Tick）
	 * \return const WTSTickStruct* Tick数据指针，无数据或索引无效时返回NULL
	 */
	inline const WTSTickStruct* at(int32_t idx)
	{
		if (_count == 0)
			return NULL;

		idx = translateIdx(idx);
		do 
		{
			for(auto& item : _blocks)
			{
				if ((uint32_t)idx >= item.second)
					idx -= item.second;
				else
					return item.first + idx;
			}
		} while (false);
		return NULL;
	}
};

//////////////////////////////////////////////////////////////////////////
/*!
 * \brief 委托明细数据切片类
 * \details 高性能的委托明细数据切片管理器，用于Level2市场委托明细的连续数据访问。
 *          采用零拷贝设计，仅记录数据起始位置和数量，提供高效的数据访问。
 *          
 *          核心特性：
 *          - 零拷贝设计：不复制数据，只保存指针和计数
 *          - 连续访问：基于连续内存的高效访问
 *          - 负索引支持：支持从末尾倒数的索引访问
 *          - 轻量级：最小的内存占用和处理开销
 *          
 *          使用场景：
 *          - Level2委托明细数据的快速访问
 *          - 大量委托数据的高效遍历
 *          - 实时委托流分析
 *          
 *          注意事项：
 *          - 依赖于底层数据的生命周期
 *          - 需确保底层数据在切片使用期间保持有效
 */
class WTSOrdDtlSlice : public WTSObject
{
private:
	char				m_strCode[MAX_INSTRUMENT_LENGTH];
	WTSOrdDtlStruct*	m_ptrBegin;
	uint32_t			m_uCount;

protected:
	WTSOrdDtlSlice() :m_ptrBegin(NULL), m_uCount(0) {}
	inline int32_t		translateIdx(int32_t idx) const
	{
		if (idx < 0)
		{
			return max(0, (int32_t)m_uCount + idx);
		}

		return idx;
	}

public:
	/*!
	 * \brief 创建委托明细数据切片对象
	 * \details 工厂方法，创建指向连续委托明细数据的切片对象。
	 * \param code 合约代码
	 * \param firstItem 委托明细数据起始指针
	 * \param count 数据条数
	 * \return WTSOrdDtlSlice* 新创建的切片对象指针，参数无效时返回NULL
	 */
	static inline WTSOrdDtlSlice* create(const char* code, WTSOrdDtlStruct* firstItem, uint32_t count)
	{
		if (count == 0 || firstItem == NULL)
			return NULL;

		WTSOrdDtlSlice* slice = new WTSOrdDtlSlice();
		wt_strcpy(slice->m_strCode, code);
		slice->m_ptrBegin = firstItem;
		slice->m_uCount = count;

		return slice;
	}

	/*!
	 * \brief 获取委托明细数据条数
	 * \return uint32_t 切片包含的委托明细总数
	 */
	inline uint32_t size() const { return m_uCount; }

	/*!
	 * \brief 检查切片是否为空
	 * \return bool true表示无数据，false表示包含数据
	 */
	inline bool empty() const { return (m_uCount == 0) || (m_ptrBegin == NULL); }

	/*!
	 * \brief 获取指定位置的委托明细数据
	 * \details 通过索引访问委托明细数据，支持负索引从末尾倒数。
	 * \param idx 数据索引，支持负值（-1表示最后一条委托明细）
	 * \return const WTSOrdDtlStruct* 委托明细数据指针，数据无效时返回NULL
	 */
	inline const WTSOrdDtlStruct* at(int32_t idx)
	{
		if (m_ptrBegin == NULL)
			return NULL;
		idx = translateIdx(idx);
		return m_ptrBegin + idx;
	}
};

//////////////////////////////////////////////////////////////////////////
/*!
 * \brief 委托队列数据切片类
 * \details 高性能的委托队列数据切片管理器，用于Level2市场委托队列的连续数据访问。
 *          采用零拷贝设计，仅记录数据起始位置和数量，提供高效的深度行情访问。
 *          
 *          核心特性：
 *          - 零拷贝设计：不复制数据，只保存指针和计数
 *          - 连续访问：基于连续内存的高效访问
 *          - 负索引支持：支持从末尾倒数的索引访问
 *          - 轻量级：最小的内存占用和处理开销
 *          
 *          使用场景：
 *          - Level2委托队列数据的快速访问
 *          - 市场深度信息的高效遍历
 *          - 实时队列状态分析
 *          - 高频交易的深度数据处理
 *          
 *          注意事项：
 *          - 依赖于底层数据的生命周期
 *          - 需确保底层数据在切片使用期间保持有效
 */
class WTSOrdQueSlice : public WTSObject
{
private:
	char				m_strCode[MAX_INSTRUMENT_LENGTH];
	WTSOrdQueStruct*	m_ptrBegin;
	uint32_t			m_uCount;

protected:
	WTSOrdQueSlice() :m_ptrBegin(NULL), m_uCount(0) {}
	inline int32_t		translateIdx(int32_t idx) const
	{
		if (idx < 0)
		{
			return max(0, (int32_t)m_uCount + idx);
		}

		return idx;
	}

public:
	/*!
	 * \brief 创建委托队列数据切片对象
	 * \details 工厂方法，创建指向连续委托队列数据的切片对象。
	 * \param code 合约代码
	 * \param firstItem 委托队列数据起始指针
	 * \param count 数据条数
	 * \return WTSOrdQueSlice* 新创建的切片对象指针，参数无效时返回NULL
	 */
	static inline WTSOrdQueSlice* create(const char* code, WTSOrdQueStruct* firstItem, uint32_t count)
	{
		if (count == 0 || firstItem == NULL)
			return NULL;

		WTSOrdQueSlice* slice = new WTSOrdQueSlice();
		wt_strcpy(slice->m_strCode, code);
		slice->m_ptrBegin = firstItem;
		slice->m_uCount = count;

		return slice;
	}

	/*!
	 * \brief 获取委托队列数据条数
	 * \return uint32_t 切片包含的委托队列总数
	 */
	inline uint32_t size() const { return m_uCount; }

	/*!
	 * \brief 检查切片是否为空
	 * \return bool true表示无数据，false表示包含数据
	 */
	inline bool empty() const { return (m_uCount == 0) || (m_ptrBegin == NULL); }

	/*!
	 * \brief 获取指定位置的委托队列数据
	 * \details 通过索引访问委托队列数据，支持负索引从末尾倒数。
	 * \param idx 数据索引，支持负值（-1表示最后一条委托队列）
	 * \return const WTSOrdQueStruct* 委托队列数据指针，数据无效时返回NULL
	 */
	inline const WTSOrdQueStruct* at(int32_t idx)
	{
		if (m_ptrBegin == NULL)
			return NULL;
		idx = translateIdx(idx);
		return m_ptrBegin + idx;
	}
};

//////////////////////////////////////////////////////////////////////////
/*!
 * \brief 成交明细数据切片类
 * \details 高性能的成交明细数据切片管理器，用于逐笔成交数据的连续访问。
 *          采用零拷贝设计，仅记录数据起始位置和数量，提供高效的成交数据访问。
 *          
 *          核心特性：
 *          - 零拷贝设计：不复制数据，只保存指针和计数
 *          - 连续访问：基于连续内存的高效访问
 *          - 负索引支持：支持从末尾倒数的索引访问
 *          - 轻量级：最小的内存占用和处理开销
 *          
 *          使用场景：
 *          - 逐笔成交数据的快速访问
 *          - 成交明细流的高效遍历
 *          - 实时成交分析
 *          - 交易量统计和分析
 *          - 高频交易的成交数据处理
 *          
 *          注意事项：
 *          - 依赖于底层数据的生命周期
 *          - 需确保底层数据在切片使用期间保持有效
 */
class WTSTransSlice : public WTSObject
{
private:
	char			m_strCode[MAX_INSTRUMENT_LENGTH];
	WTSTransStruct*	m_ptrBegin;
	uint32_t		m_uCount;

protected:
	WTSTransSlice() :m_ptrBegin(NULL), m_uCount(0) {}
	inline int32_t		translateIdx(int32_t idx) const
	{
		if (idx < 0)
		{
			return max(0, (int32_t)m_uCount + idx);
		}

		return idx;
	}

public:
	/*!
	 * \brief 创建成交明细数据切片对象
	 * \details 工厂方法，创建指向连续成交明细数据的切片对象。
	 * \param code 合约代码
	 * \param firstItem 成交明细数据起始指针
	 * \param count 数据条数
	 * \return WTSTransSlice* 新创建的切片对象指针，参数无效时返回NULL
	 */
	static inline WTSTransSlice* create(const char* code, WTSTransStruct* firstItem, uint32_t count)
	{
		if (count == 0 || firstItem == NULL)
			return NULL;

		WTSTransSlice* slice = new WTSTransSlice();
		wt_strcpy(slice->m_strCode, code);
		slice->m_ptrBegin = firstItem;
		slice->m_uCount = count;

		return slice;
	}

	/*!
	 * \brief 获取成交明细数据条数
	 * \return uint32_t 切片包含的成交明细总数
	 */
	inline uint32_t size() const { return m_uCount; }

	/*!
	 * \brief 检查切片是否为空
	 * \return bool true表示无数据，false表示包含数据
	 */
	inline bool empty() const { return (m_uCount == 0) || (m_ptrBegin == NULL); }

	/*!
	 * \brief 获取指定位置的成交明细数据
	 * \details 通过索引访问成交明细数据，支持负索引从末尾倒数。
	 * \param idx 数据索引，支持负值（-1表示最后一条成交明细）
	 * \return const WTSTransStruct* 成交明细数据指针，数据无效时返回NULL
	 */
	inline const WTSTransStruct* at(int32_t idx)
	{
		if (m_ptrBegin == NULL)
			return NULL;
		idx = translateIdx(idx);
		return m_ptrBegin + idx;
	}
};

NS_WTP_END